//
//  AppDelegate.m
//  InduceTool
//
//  Created by 魏延龙 on 2020/8/3.
//  Copyright © 2020 魏延龙. All rights reserved.
//

#import "AppDelegate.h"
#import "ITReplacingResourceURLProtocol.h"
#import <LEETheme/LEETheme.h>
#import "ITWKWebViewController.h"
#include <execinfo.h>
#import "NSException+JKTrace.h"
#ifdef DEBUG
#import <DoraemonKit/DoraemonManager.h>
#import "ITPluginViewController.h"
#endif

typedef void(^CompletionHandlerType)();

@interface AppDelegate ()

@property(nonatomic, copy) CompletionHandlerType handler;
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    NSLog(@"didFinishLaunchingWithOptions %f", application.backgroundTimeRemaining);
    
    #ifdef DEBUG
    [self configDoraemonKit];
    #endif
    
    [self configTheme];
//    installUncaughtExceptionHandler();
//    registerSignalHandler();
//    installSignalHandler();
    return YES;
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // 可以通过这个值判断是否被动启动
    NSLog(@"applicationDidBecomeActive %f", application.backgroundTimeRemaining);
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
    NSLog(@"applicationDidEnterBackground  %f", application.backgroundTimeRemaining);
}

//配置Doraemon工具集
- (void)configDoraemonKit{
    [[DoraemonManager shareInstance] addPluginWithTitle:@"环境切换" icon:@"doraemon_default" desc:@"用于app内部环境切换功能" pluginName:@"ITPluginViewController" atModule:@"业务专区" handle:^(NSDictionary * _Nonnull itemData) {
        UINavigationController *navi = (UINavigationController *)self.window.rootViewController;
        [navi pushViewController:[ITPluginViewController new] animated:YES];
    }];
    [[DoraemonManager shareInstance] installWithPid:@"productId"];
}

// 配置主题
- (void)configTheme {
    NSString *grayJsonPath = [[NSBundle mainBundle] pathForResource:@"tag_gray_json" ofType:@"json"];
    NSString *greenJsonPath = [[NSBundle mainBundle] pathForResource:@"tag_green_json" ofType:@"json"];
    NSString *redJsonPath = [[NSBundle mainBundle] pathForResource:@"tag_red_json" ofType:@"json"];
    NSString *grayJson = [NSString stringWithContentsOfFile:grayJsonPath encoding:NSUTF8StringEncoding error:nil];
    NSString *greenJson = [NSString stringWithContentsOfFile:greenJsonPath encoding:NSUTF8StringEncoding error:nil];
    NSString *redJson = [NSString stringWithContentsOfFile:redJsonPath encoding:NSUTF8StringEncoding error:nil];
    [LEETheme defaultTheme:@"gray"];
    [LEETheme addThemeConfigWithJson:grayJson Tag:@"gray" ResourcesPath:nil];
    [LEETheme addThemeConfigWithJson:greenJson Tag:@"green" ResourcesPath:nil];
    [LEETheme addThemeConfigWithJson:redJson Tag:@"red" ResourcesPath:nil];
}

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(nonnull NSString *)identifier completionHandler:(nonnull void (^)(void))completionHandler{
//    self.handler = completionHandler;
}

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    NSLog(@"application openURL %@", url);
    UINavigationController *navi = (UINavigationController *)self.window.rootViewController;
    if ([url.absoluteString isEqualToString:@"todaytool://wkwebview"] && ![navi.viewControllers.lastObject isKindOfClass:[ITWKWebViewController class]]) {
        [navi pushViewController:[ITWKWebViewController new] animated:YES];
    }
    return YES;
}



static NSUncaughtExceptionHandler* g_previousUncaughtExceptionHandler;

void installUncaughtExceptionHandler(void){
    g_previousUncaughtExceptionHandler = NSGetUncaughtExceptionHandler();
    NSSetUncaughtExceptionHandler(&uncaughtHandleException);
}
void uninstallUncaughtExceptionHandler(void){
    if(g_previousUncaughtExceptionHandler){
        NSSetUncaughtExceptionHandler(g_previousUncaughtExceptionHandler);
    }
}

void uncaughtHandleException(NSException *exception){
    NSArray *ar = [exception jk_backtrace];
    NSLog(@"-------------%@",ar);
    // 异常的堆栈信息
    NSArray *stackArray = [exception callStackSymbols];
    // 出现异常的原因
    NSString *reason = [exception reason];
    // 异常名称
    NSString *name = [exception name];
    NSString *exceptionInfo = [NSString stringWithFormat:@"Exception reason：%@\nException name：%@\nException stack：%@",name, reason, stackArray];
    NSLog(exceptionInfo);
    if (g_previousUncaughtExceptionHandler != NULL){
        g_previousUncaughtExceptionHandler(exception);
    }
}



void registerSignalHandler(void) {
//    signal(SIGSEGV, handleSignalException);
//    signal(SIGFPE, handleSignalException);
//    signal(SIGBUS, handleSignalException);
//    signal(SIGPIPE, handleSignalException);
//    signal(SIGHUP, handleSignalException);
//    signal(SIGINT, handleSignalException);
//    signal(SIGQUIT, handleSignalException);
    signal(SIGABRT, handleSignalException);
//    signal(SIGILL, handleSignalException);
    
}

void handleSignalException(int signal) {
    NSMutableString *crashString = [[NSMutableString alloc]init];
    void* callstack[128];
    int i, frames = backtrace(callstack, 128);
    char** traceChar = backtrace_symbols(callstack, frames);
    for (i = 0; i <frames; ++i) {
        [crashString appendFormat:@"------------%s\n", traceChar[i]];
    }
    NSLog(@"------%@",crashString);
}



static struct sigaction* g_previousSignalHandlers = NULL;
//旧的信号处理函数结构体数组
static int g_fatalSignals[] = {    SIGHUP,    SIGINT,    SIGQUIT,    SIGABRT,    SIGILL,    SIGSEGV,    SIGFPE,    SIGBUS,    SIGPIPE};
static int g_fatalSignalsCount = (sizeof(g_fatalSignals) / sizeof(g_fatalSignals[0]));
const int* kssignal_fatalSignals(void){return g_fatalSignals;}
int kssignal_numFatalSignals(void){return g_fatalSignalsCount;}

void signalExceptionHandler(int signo, siginfo_t *info, void *uapVoid){
    void *frames[128];
    int i, len = backtrace(frames, 128);
    //堆栈信息
    char **symbols = backtrace_symbols(frames, len);
    NSMutableString *exceptionContent = [[NSMutableString alloc] init];
    [exceptionContent appendFormat:@"signal name：%d \n signal stack：\n",signo];
    for (i = 0; i < len; ++i)    {
        [exceptionContent appendFormat:@"%s\r\n", symbols[i]];
    }
    //释放缓存
    free(symbols);
    raise(signo);
}

void installSignalHandler(void){
    const int* fatalSignals = kssignal_fatalSignals();
    int fatalSignalsCount = kssignal_numFatalSignals();
    if(g_previousSignalHandlers == NULL){
        g_previousSignalHandlers = (struct sigaction *)malloc(sizeof(*g_previousSignalHandlers) * (unsigned)fatalSignalsCount);
    }    //初始化处理函数结构体
    struct sigaction action = {{0}};
    action.sa_flags = SA_SIGINFO | SA_ONSTACK;
    sigemptyset(&action.sa_mask);
    action.sa_sigaction = &signalExceptionHandler;
    for(int i = 0; i < fatalSignalsCount; i++)    {
        if(sigaction(fatalSignals[i], &action, &g_previousSignalHandlers[i]) != 0){
            // 取消已监听的handler
            for(i--;i >= 0; i--){
                sigaction(fatalSignals[i], &g_previousSignalHandlers[i], NULL);
            }
            break;
        }
    }
}
void uninstallSignalHandler(void){
    const int* fatalSignals = kssignal_fatalSignals();
    int fatalSignalsCount = kssignal_numFatalSignals();
    for(int i = 0; i < fatalSignalsCount; i++)    {
        sigaction(fatalSignals[i], &g_previousSignalHandlers[i], NULL);
    }
}
@end
